package com.yilin.tms.core.components.filter;

import cn.hutool.json.JSONUtil;
import com.google.gson.reflect.TypeToken;
import com.yilin.commons.util.CommonUtil;
import com.yilin.commons.util.JsonUtil;
import com.yilin.commons.util.StreamUtil;
import com.yilin.commons.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.*;

/**
 * 过滤器：请求数据重构
 */
@Component
//@WebFilter(filterName = "decryptFilter", urlPatterns = "/*")
@Order(1) //测试好像这个参数不生效，实际生效的是Filter扫描到的顺序（所以起名很重要）
public class ReqBindingFilter implements Filter {
    private Logger logger = LoggerFactory.getLogger(ReqBindingFilter.class);

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request = new ReqBindingFilterWrapper((HttpServletRequest) request);
        chain.doFilter(request, response);
    }

    /**
     * 过滤器：数据重构
     */
    private static class ReqBindingFilterWrapper extends HttpServletRequestWrapper {
        private Map<String, Object> bodyMap = new HashMap<>();
        private Map<String, Object> paramMap = new HashMap<>();

        boolean original = false;

        ReqBindingFilterWrapper(HttpServletRequest request) throws IOException {
            super(request);
            request.setCharacterEncoding("UTF-8");
            String jsonData = request.getParameter("body");
            //平台调用走的也是下面
            if (StringUtil.isEmpty(jsonData)) jsonData = StreamUtil.getBodyString(request.getInputStream());
            if (StringUtil.isNotEmpty(jsonData) && JsonUtil.isJson(jsonData)) {
                this.bodyMap = JsonUtil.jsonToObject(jsonData, new TypeToken<Map<String, Object>>() {});
                this.paramMap = JsonUtil.jsonToObject(jsonData, new TypeToken<Map<String, Object>>() {});
                setChildMap(bodyMap);
            } else {
                original = true;
            }
        }

        //MAP实体子类转换
        @SuppressWarnings("unchecked")
        private void setChildMap(Map<String, Object> paramMap) {
            if (paramMap == null) {
                return;
            }
            List<String> mapKeys = new ArrayList<>();
            List<String> listKeys = new ArrayList<>();
            boolean hasMap = false;
            boolean hasList = false;
            for (String paramKey : paramMap.keySet()) {
                if (paramMap.get(paramKey) == null) {
                } else if (paramMap.get(paramKey) instanceof Map) {
                    mapKeys.add(paramKey);
                    hasMap = true;
                } else if (paramMap.get(paramKey) instanceof List) {
                    listKeys.add(paramKey);
                    hasList = true;
                } else if (paramMap.get(paramKey) instanceof Double) {
                    paramMap.put(paramKey, CommonUtil.trimNumber(String.valueOf(paramMap.get(paramKey))));
                } else {
                    paramMap.put(paramKey, String.valueOf(paramMap.get(paramKey)));
                }
            }
            for (String removeKey : mapKeys) {
                Map<String, Object> childMap = (Map<String, Object>) paramMap.get(removeKey);
                for (String childKey : childMap.keySet()) {
                    paramMap.put(removeKey + "." + childKey, childMap.get(childKey));
                }
                paramMap.remove(removeKey);
            }
            for (String removeKey : listKeys) {
                List<Object> list = (List<Object>) paramMap.get(removeKey);
                for (int i = 0; i < list.size(); i++) {// "obh.list.0.sss"
                    paramMap.put(removeKey + "[" + i + "]", list.get(i));
                }
                paramMap.remove(removeKey);
            }
            if (hasMap || hasList) {
                setChildMap(paramMap);
            }
        }

        //返回所有参数名
        @SuppressWarnings("rawtypes")
        @Override
        public Enumeration getParameterNames() {
            if (original) return super.getParameterNames();
            if (bodyMap == null) return null;
            setChildMap(bodyMap);
            Vector<String> names = new Vector<>(this.bodyMap.keySet());
            return names.elements();
        }

        //获取所有参数值
        @Override
        public String[] getParameterValues(String name) {
            if (original) return super.getParameterValues(name);
            if (bodyMap == null || bodyMap.get(name) == null || StringUtil.isEmpty(bodyMap.get(name).toString())) {
                return null;
            }
            String data = bodyMap.get(name).toString();
            return new String[]{data};
        }

        //获取参数值
        @Override
        public String getParameter(String name) {
            if (StringUtil.isEmpty(name)) return null;
            if (original) return super.getParameter(name);
            if (paramMap == null || paramMap.get(name) == null || StringUtil.isEmpty(paramMap.get(name).toString())) {
                return null;
            }
            return JSONUtil.toJsonStr(paramMap.get(name));
        }
    }
}
